#ifndef PRIMITIVE_H_
#define PRIMITIVE_H_
#include <iostream>
#include <string>
#include <list>
#include <map>
#include <algorithm>

#include "PrimitiveType.h"
#include "../basic/Point.h"
#include "../basic/MyException.h"
#include "../Config.h"
#include "../ads/typesDefinition.h"

namespace common {

class Primitive: public common::IdAble,public ToStringAble {

	typedef std::map<int, Point*> pointMap;

	PrimitiveType type;
	/** zbior wszystkich punktow, kolejnosc wazna */
	pointMap points;

	/**
	 * Dodajemy na koniec mapy dany punkt
	 */
	void addPoint(Point* p);

protected:

	/**
	 * Funkcja zwraca pozycje od(o..n) na ktorej znajduje sie punkt
	 * w mapie punktow
	 */
	int getPointPosition(Point* p);

public:
	/** Konstruktor na elementy typu segment */
	Primitive(const int& id, const PrimitiveType& type, std::list<Point*>& pointSet);
	/** Konstruktor na elementy typu LINE ,CIRCLE,*/
	Primitive(const int& id, const PrimitiveType& type, Point* p1,Point* p2);

	/*
	 * Relax punktow, czyli ustawienie pozycji punktow
	 * tak aby siły w sprezynach spadly do zera
	 */
	virtual void relax();
	/**
	 * Funkcja zwraca siłe w danym punkcie ,
	 * wynik otrzymujemy w postaci vektora [val1,val2]' = [x,y]';
	 */
	virtual ublasVector getForceInPoint(Point* p);

	/**
	 * Zwraca sile dla wszystkich punktow w kolejnosc
	 * wystepowania w mapie
	 */
	virtual ublasVector getForceAll();

	/**
	 * Funkcja zwraca Jacobian  = macierz sztywnosci na
	 * przecieciu punktu i - wiersz , j kolumna
	 */
	virtual ublasMatrix getJacobian(Point* i, Point* j);

	/**
	 * Zwraca Jacobian dla wszystkich punktow w jednym bloku
	 */
	virtual ublasMatrix getJacobianAll();

	/**
	 * Czy Jakobian zalezy od tych 2 punktow,
	 * Zalezy tylko gdy te dwa punktu naleza do zbioru elementow = points
	 */
	bool isJacobianDependsOn(Point* i, Point* j);
	/**
	 * Zwraca wszystkie punkty powiazane z dana figura
	 */
	std::list<Point*> getAllPoints(void);

	/**
	 * Funkcja zwraca punkt na danej pozycji w figurze
	 * Kolejnosc jest wazna : np SEGMENT - macierz sztywnosci wyglada inaczej
	 *
	 *
	 */
	Point* getPoint(const int& id);


	/**
	 * Zwraca liczbe punktow w danym elemencie
	 */
	int getNumOfPoints();

	std::string getTypeToString();

	std::string toString(void);

	virtual ~Primitive();
};

}

#endif /* PRIMITIVE_H_ */
